﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Text;
using System.Data.Objects.DataClasses;

using FRL.DebtChased.WebServices;

namespace FRL.DebtChased.Repository
{

	/// <summary>
	/// Extensions to the Client model
	/// </summary>
	public partial class Client
	{

		/////////////////////////////////////////////////////////////
		// Attributes

		public Definitions.eClientInvoicingFrequency InvoicingFrequency
		{
			get { return (Definitions.eClientInvoicingFrequency)fdInvoicingFrequency; }
			set { fdInvoicingFrequency = (int)value; }
		}

		public Definitions.eClientInvoiceStatementTravel InvoiceTravel
		{
			get { return (Definitions.eClientInvoiceStatementTravel)fdInvoiceTravel; }
			set { fdInvoiceTravel = (int)value; }
		}

		public Definitions.eClientStatementFrequency StatementFrequency
		{
			get { return (Definitions.eClientStatementFrequency)fdStatementFrequency; }
			set { fdStatementFrequency = (int)value; }
		}

		public Definitions.eClientInvoiceStatementTravel StatementTravel
		{
			get { return (Definitions.eClientInvoiceStatementTravel)fdStatementTravel; }
			set { fdStatementTravel = (int)value; }
		}

		public Definitions.eClientFundsSettings ClientFundsSettings
		{
			get { return (Definitions.eClientFundsSettings)fdClientFundsSettings; }
			set { fdClientFundsSettings = (int)value; }
		}

		public Definitions.eClientFundsFrequency FundsFrequency
		{
			get { return (Definitions.eClientFundsFrequency)fdClientFundsFrequency; }
			set { fdClientFundsFrequency = (int)value; }
		}

		public Definitions.eClientAccountStatus ClientAccountStatus
		{
			get { return (Definitions.eClientAccountStatus)fdClientAccountStatus; }
			set { fdClientFundsSettings = (int)value; }
		}

		public Definitions.eClientPaymentMethod PaymentMethod
		{
			get { return (Definitions.eClientPaymentMethod)fdPaymentMethod; }
			set { fdPaymentMethod = (int)value; }
		}

		public Definitions.eClientCommsType CommsType
		{
			get { return (Definitions.eClientCommsType)fdCommsType; }
			set { fdCommsType = (int)value; }
		}

		public Definitions.eClientCommsFrequency CommsFrequency
		{
			get { return (Definitions.eClientCommsFrequency)fdCommsFrequency; }
			set { fdCommsFrequency = (int)value; }
		}

		/////////////////////////////////////////////////////////////
		// Static Operations

		public static Dictionary<int, string> GetDictionary(DebtChasedEntities ent)
		{

			// Load the clients
			var clients = from c in ent.Clients
						  orderby c.Name
						  select new { c.ClientId, c.Name };

			// Create dictionary
			return clients.ToDictionary(c => c.ClientId, c => c.Name);

		}

		public static List<string> GetActivities(DebtChasedEntities ent)
		{

			// Load exising activities
			return (from c in ent.Clients
							 orderby c.Activity
							 select c.Activity).Distinct().ToList();

		}

		public static string GetName(DebtChasedEntities ent, int iClientId)
		{

			// Load the client name
			return (from c in ent.Clients
					where c.ClientId == iClientId
					select c.Name).FirstOrDefault();

		}

		public static void UserIdToClient(
			DebtChasedEntities ent, 
			int iUserId, 
			ref int iClientId, 
			ref int iClientContactId,
			ref string strClientName 
		)
		{

			// Load the client name
			var result = (
				from c in ent.Clients
				join cc in ent.ClientContacts on c.ClientId equals cc.ClientId
				join u in ent.Users on cc.ClientContactId equals u.ClientContactId
				where u.UserId == iUserId
				select new { c.ClientId, cc.ClientContactId, c.Name }
			).FirstOrDefault();
			if (result == null)
			{

				// Reset function parameters
				iClientId = 0;
				iClientContactId = 0;
				strClientName = null;

			}
			else
			{

				// Set function parameters
				iClientId = result.ClientId;
				iClientContactId = result.ClientContactId;
				strClientName = result.Name;

			}

		}

		public static AccountPrimaryClientTransport GetPrimaryClientTransport(DebtChasedEntities ent, int iClientId, int iClientContactId)
		{

			// Declare return variable
			AccountPrimaryClientTransport Ftmp = null;

			// Load the client details
			Client client = (from c in ent.Clients.Include("ClientBankAccounts")
						     where (c.ClientId == iClientId)
						     select c).FirstOrDefault();

			// If record found...
			if (client != null)
			{

				// Set object members
				Ftmp = new AccountPrimaryClientTransport();
				Ftmp.ClientId = client.ClientId;
				Ftmp.Name = client.Name;
				Ftmp.Website = client.Website;
				Ftmp.Notes = string.Empty;

				// Get the bank accounts
				Ftmp.BankAccounts = ClientBankAccount.GetTransportList(client);

				// Get the primary contact
				Ftmp.PrimaryContact = ClientContact.GetTransport(ent, iClientContactId);

			}

			// Return variable
			return Ftmp;

		}

		public static ClientTransport GetClientTransport( DebtChasedEntities ent, int iClientId )
		{

			// Declare return variable
			ClientTransport Ftmp = null;

			// Load the client details
			Client client = (from c in ent.Clients.Include("ClientBankAccounts")
						     where (c.ClientId == iClientId)
						     select c).FirstOrDefault();

			// If record found...
			if (client != null)
			{

				// Set object members
				Ftmp = new ClientTransport();
				Ftmp.ClientId = client.ClientId;
				Ftmp.Name = client.Name;
				Ftmp.Website = client.Website;
				Ftmp.Activity = client.Activity;
				Ftmp.InvoicingFrequency = client.fdInvoicingFrequency;
				Ftmp.InvoiceTravel = client.fdInvoiceTravel;
				Ftmp.StatementFrequency = client.fdStatementFrequency;
				Ftmp.StatementTravel = client.fdStatementTravel;
				Ftmp.VATNumber = client.VATNumber;
				Ftmp.InvoicingCurrency = client.InvoicingCurrency;
				Ftmp.ClientFundsSettings = client.fdClientFundsSettings;
				Ftmp.ClientAccountStatus = client.fdClientAccountStatus;
				Ftmp.ClientFundsFrequency = client.fdClientFundsFrequency;
				Ftmp.PaymentMethod = client.fdPaymentMethod;
				Ftmp.SalesContactId = client.SalesContactId ?? 0;
				Ftmp.FinanceTeamId = client.FinanceTeamId ?? 0;
				Ftmp.InvoiceContactId = client.InvoiceContactId ?? 0;
				Ftmp.CommsType = client.fdCommsType;
				Ftmp.CommsFrequency = client.fdCommsFrequency;
				Ftmp.CommsContactId = client.CommsContactId ?? 0;
				Ftmp.CommsContactCCIdA = client.CommsContactCCIdA ?? 0;
				Ftmp.CommsContactCCIdB = client.CommsContactCCIdB ?? 0;
				Ftmp.HolidayContactId = client.HolidayContactId ?? 0;
				Ftmp.IsHolidayActivated = client.IsHolidayActivated;
				Ftmp.HolidayContactCCId = client.HolidayContactId ?? 0;
				Ftmp.HolidayStartAt = client.HolidayStartAt;
				Ftmp.HolidayEndAt = client.HolidayEndAt;

				// Get the bank accounts
				Ftmp.BankAccounts = ClientBankAccount.GetTransportList( client );

				// Get the instruction batch list
				Ftmp.ClientInstructionBatchList = ClientInstructionBatch.GetTransportList( ent, client );

				// Get the contacts
				Ftmp.Contacts = ClientContact.GetTransportList( client );

			}

			// Return variable
			return Ftmp;

		}

		public static string SetClientTransport( DebtChasedEntities ent, ClientTransport clientTransport, int iUserId )
		{
#if DEBUG
			Debug.Assert(clientTransport.Contacts != null);
			Debug.Assert(clientTransport.BankAccounts != null);
#endif // #if DEBUG

			// Declare return variable
			string strError = null;

			try
			{

				// Start by getting a client objects
				Client currentClient = null;
				if (clientTransport.ClientId == 0)
				{

					// Create a new client
					currentClient = Client.CreateClient(0, string.Empty, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, (int)Definitions.eClientCommsFrequency.Weekly);
					ent.Clients.AddObject(currentClient);

				}
				else
				{

					// Load the client details including bank acccounts and batches
					currentClient = (from c in ent.Clients.Include("ClientBankAccounts").Include("ClientInstructionBatches").Include("ClientContacts")
								where (c.ClientId == clientTransport.ClientId)
								select c).First();
#if DEBUG
					Debug.Assert(currentClient != null);
#endif // #if DEBUG

				}

				// Track user activity
				UserAction.Session session = new UserAction.Session(iUserId, currentClient, clientTransport.Name);

				// Process bank accounts
				ClientBankAccount.InterCursorSetFromTransport(ent, session, currentClient, clientTransport, iUserId);

				// Process instruction batch lists
				ClientInstructionBatch.InterCursorSetFromTransport(ent, session, currentClient, clientTransport, iUserId);

				// Process contacts
				Dictionary<int, ClientContact> contactMap = new Dictionary<int, ClientContact>();
				ClientContact.InterCursorSetFromTransport(ent, session, currentClient, clientTransport, contactMap, iUserId);

				// Update the client
				if(currentClient.Website != clientTransport.Website)
					currentClient.Website = clientTransport.Website;

				if (currentClient.Name != clientTransport.Name)
					currentClient.Name = clientTransport.Name;

				if (currentClient.Activity != clientTransport.Activity)
					currentClient.Activity = clientTransport.Activity;

				if(currentClient.fdInvoicingFrequency != clientTransport.InvoicingFrequency)
					currentClient.fdInvoicingFrequency = clientTransport.InvoicingFrequency;

				if(currentClient.fdInvoiceTravel != clientTransport.InvoiceTravel)
					currentClient.fdInvoiceTravel = clientTransport.InvoiceTravel;

				if(currentClient.fdStatementFrequency != clientTransport.StatementFrequency)
					currentClient.fdStatementFrequency = clientTransport.StatementFrequency;

				if(currentClient.fdStatementTravel != clientTransport.StatementTravel)
					currentClient.fdStatementTravel = clientTransport.StatementTravel;

				if(currentClient.VATNumber != clientTransport.VATNumber)
					currentClient.VATNumber = clientTransport.VATNumber;

				string strTemp = string.IsNullOrEmpty(clientTransport.InvoicingCurrency) ? null : clientTransport.InvoicingCurrency;
				if(currentClient.InvoicingCurrency != strTemp)
					currentClient.InvoicingCurrency = strTemp;

				if(currentClient.fdClientFundsSettings != clientTransport.ClientFundsSettings)
					currentClient.fdClientFundsSettings = clientTransport.ClientFundsSettings;

				if(currentClient.fdClientAccountStatus != clientTransport.ClientAccountStatus)
					currentClient.fdClientAccountStatus = clientTransport.ClientAccountStatus;

				if(currentClient.fdClientFundsFrequency != clientTransport.ClientFundsFrequency)
					currentClient.fdClientFundsFrequency = clientTransport.ClientFundsFrequency;

				if(currentClient.fdPaymentMethod != clientTransport.PaymentMethod)
					currentClient.fdPaymentMethod = clientTransport.PaymentMethod;

				int? iTemp = clientTransport.FinanceTeamId == 0 ? default(int?) : clientTransport.FinanceTeamId;
				if(currentClient.FinanceTeamId != iTemp)
					currentClient.FinanceTeamId = iTemp;

				if (currentClient.fdCommsType != clientTransport.CommsType)
					currentClient.fdCommsType = clientTransport.CommsType;

				if (currentClient.fdCommsFrequency != clientTransport.CommsFrequency)
					currentClient.fdCommsFrequency = clientTransport.CommsFrequency;

				if (currentClient.IsHolidayActivated != clientTransport.IsHolidayActivated)
					currentClient.IsHolidayActivated = clientTransport.IsHolidayActivated;

				if(currentClient.HolidayEndAt != clientTransport.HolidayEndAt)
					currentClient.HolidayEndAt = clientTransport.HolidayEndAt;

				// Nullify contact references
				currentClient.SalesContact = null;
				currentClient.InvoiceContact = null;
				currentClient.CommsContact = null;
				currentClient.CommsContactCCA = null;
				currentClient.CommsContactCCB = null;
				currentClient.HolidayContact = null;
				currentClient.HolidayContactCC = null;

				// Save changes
				ent.SaveChanges();

				// Update client
				if (clientTransport.ClientId == 0)
					clientTransport.ClientId = currentClient.ClientId;
#if DEBUG
				else
					Debug.Assert(clientTransport.ClientId == currentClient.ClientId);
#endif // #if DEBUG

				// Add the session objects
				session.SaveChanges(ent);

				/////////////////////////////////////////////////////
				#region SET CONTACT ENTITY OBJECTS

				// Set contact entity object - sales contact
				if (clientTransport.SalesContactId != 0)
				{
					if (contactMap.ContainsKey(clientTransport.SalesContactId))
						currentClient.SalesContact = contactMap[clientTransport.SalesContactId];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				// Set contact entity object - invoice contact
				if (clientTransport.InvoiceContactId != 0)
				{
					if (contactMap.ContainsKey(clientTransport.InvoiceContactId))
						currentClient.InvoiceContact = contactMap[clientTransport.InvoiceContactId];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				// Set contact entity object - comms contact
				if (clientTransport.CommsContactId != 0)
				{
					if (contactMap.ContainsKey(clientTransport.CommsContactId))
						currentClient.CommsContact = contactMap[clientTransport.CommsContactId];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				// Set contact entity object - comms contact A
				if (clientTransport.CommsContactCCIdA != 0)
				{
					if (contactMap.ContainsKey(clientTransport.CommsContactCCIdA))
						currentClient.CommsContactCCA = contactMap[clientTransport.CommsContactCCIdA];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				// Set contact entity object - comms contact B
				if (clientTransport.CommsContactCCIdB != 0)
				{
					if (contactMap.ContainsKey(clientTransport.CommsContactCCIdB))
						currentClient.CommsContactCCB = contactMap[clientTransport.CommsContactCCIdB];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				// Set contact entity object - holiday contact
				if (clientTransport.HolidayContactId != 0)
				{
					if (contactMap.ContainsKey(clientTransport.HolidayContactId))
						currentClient.HolidayContact = contactMap[clientTransport.HolidayContactId];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				// Set contact entity object - holiday contact CC
				if (clientTransport.HolidayContactCCId != 0)
				{
					if (contactMap.ContainsKey(clientTransport.HolidayContactCCId))
						currentClient.HolidayContactCC = contactMap[clientTransport.HolidayContactCCId];
#if DEBUG
					else
						Debug.Assert(false);
#endif // #if DEBUG
				}

				#endregion

				// If there are changes to be applied...
				if (currentClient.EntityState != System.Data.EntityState.Unchanged)
					ent.SaveChanges();

			}
			catch (Exception x)
			{

				// Handle exception
				strError = ErrorProcessing.HandleException(x, "save client", iUserId);

			}

			// Return variable
			return strError;

		}

		public static List<ClientSummaryTransport> TransportSearch(DebtChasedEntities ent, string strSearch)
		{

			// Declare return variable
			List<ClientSummaryTransport> Ftmp = new List<ClientSummaryTransport>();

			// Format search string
			if (!strSearch.Contains("%"))
				strSearch = string.Format("%{0}%", strSearch);

			// Load from SP function
			var results = ent.SearchClientsProc(strSearch);
			foreach (var result in results)
			{

				// Load the return variable
				ClientSummaryTransport cst = new ClientSummaryTransport();
				Ftmp.Add(cst);
				cst.ClientId = result.fdClientId;
				cst.Contacts = result.fdContacts;
				cst.Name = result.fdName;

			}

			// Return variable
			return Ftmp;

		}

	}

}
